/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.lvyh.lightframe.job.admin.util;

import com.alibaba.fastjson.JSON;
import com.google.common.base.Joiner;
import com.lvyh.lightframe.job.client.InvokeResult;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.http.HttpEntity;
import org.apache.http.NameValuePair;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.util.EntityUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

public class HttpUtils {

    private static final Logger logger = LoggerFactory.getLogger(HttpUtils.class);

    public static InvokeResult doGet(String url, int timeout, Map<String, String> params) throws IOException, URISyntaxException {

        CloseableHttpClient client = HttpClients.custom().setDefaultRequestConfig(
                RequestConfig.custom().setConnectionRequestTimeout(timeout)
                        .setConnectTimeout(timeout)
                        .setSocketTimeout(timeout).build()).build();
        CloseableHttpResponse response = null;
        String httpUrl = url;
        try {

            if (params != null) {
                String paramsStr = Joiner.on("&").withKeyValueSeparator("=").join(params);
                if (StringUtils.isNotBlank(paramsStr)) {
                    if (StringUtils.indexOf(url, "?") != -1) {
                        httpUrl = url + "&" + paramsStr;
                    } else {
                        httpUrl = url + "?" + paramsStr;
                    }
                }
            }

            URL _url = new URL(httpUrl);
            URI uri = new URI(_url.getProtocol(), null, _url.getHost(), _url.getPort(), _url.getPath(), _url.getQuery(), null);
            HttpGet get = new HttpGet(uri);
            get.setHeader("User-Agent", "job_schedule");

            response = client.execute(get);

            return handleResult(response);
        } catch (Exception e) {
            logger.error("HTTP-RPC-ERR:{}.  url={}", e.getMessage(), url);
            InvokeResult retResult = new InvokeResult();
            retResult.setSuccess(false);
            retResult.setFailedCount(1);
            retResult.setCode("HTTP-RPC-ERR");
            retResult.setDescription(e.getMessage());
            return retResult;
        } finally {
            if (response != null) {
                IOUtils.closeQuietly(response);
            }
            if (client != null) {
                IOUtils.closeQuietly(client);
            }
        }
    }

    public static InvokeResult doPost(String url, int timeout, Map<String, String> params) throws IOException {

        CloseableHttpClient client = HttpClients.custom().setDefaultRequestConfig(
                RequestConfig.custom().setConnectionRequestTimeout(timeout)
                        .setConnectTimeout(timeout)
                        .setSocketTimeout(timeout).build()).build();
        CloseableHttpResponse response = null;
        try {
            HttpPost post = new HttpPost(url);
            post.setHeader("User-Agent", "job_schedule");

            List<NameValuePair> formparams = new ArrayList<NameValuePair>();
            if (params != null) {
                for (Map.Entry<String, String> entry : params.entrySet()) {
                    formparams.add(new BasicNameValuePair(entry.getKey(), entry.getValue()));
                }
                UrlEncodedFormEntity uefEntity = new UrlEncodedFormEntity(formparams, "UTF-8");
                post.setEntity(uefEntity);
            }

            response = client.execute(post);

            return handleResult(response);
        } catch (Exception e) {
            logger.error("HTTP-RPC-ERR:{}.  url={}", e.getMessage(), url);
            InvokeResult retResult = new InvokeResult();
            retResult.setCode("HTTP-RPC-ERR");
            retResult.setSuccess(false);
            retResult.setFailedCount(1);
            retResult.setDescription(e.getMessage());
            return retResult;
        } finally {
            if (response != null) {
                IOUtils.closeQuietly(response);
            }
            if (client != null) {
                IOUtils.closeQuietly(client);
            }
        }
    }

    @SuppressWarnings("unused")
    private static InvokeResult handleResult(CloseableHttpResponse response) throws IOException {
        InvokeResult invokeResult = null;
        int statusCode = response.getStatusLine().getStatusCode();
        if (statusCode != 200) {
            throw new RuntimeException("HttpCode_" + statusCode);
        }

        HttpEntity ety = response.getEntity();
        String content = EntityUtils.toString(ety, "UTF-8");
        InvokeResult result = JSON.parseObject(content, InvokeResult.class);
        if (result != null && !result.isSuccess() && StringUtils.isEmpty(result.getDescription())) {
            result.setDescription("unknown error");
        }
        return result;
    }

    public static boolean isAjax(HttpServletRequest request) {
        return "XMLHttpRequest".equals(request.getHeader("X-Requested-With")) ? true : false;
    }

    public static boolean isGet(HttpServletRequest request) {
        if ("GET".equalsIgnoreCase(request.getMethod())) {
            return true;
        }
        return false;
    }

    public static boolean isPost(HttpServletRequest request) {
        if ("POST".equalsIgnoreCase(request.getMethod())) {
            return true;
        }
        return false;
    }

    public static void ajaxStatus(HttpServletResponse response, int status, String tip) {
        try {
            response.setContentType("application/json;charset=UTF-8");
            response.setStatus(status);
            PrintWriter out = response.getWriter();
            out.print(tip);
            out.flush();
        } catch (IOException e) {
            logger.error(e.toString());
        }
    }

}
